package be.rivendale.mathematics;

import org.junit.Test;

import static be.rivendale.mathematics.MathematicalAssert.assertRealEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

public class MathematicalUtilitiesTest {
    @Test
    public void equalsBetweenTwoDoublesReturnsTrueIfBothAreEqual() throws Exception {
        assertTrue(MathematicalUtilities.equals(0.000001, 0.000001));
    }

    @Test
    public void equalsBetweenTwoDoublesReturnsFalseIfBothAreNotEqual() throws Exception {
        assertFalse(MathematicalUtilities.equals(0.000001, 0.000002));
    }

    @Test
    public void betweenReturnsFalseIfTheBetweenValueIsLessThenTheLowValue() throws Exception {
        assertFalse(MathematicalUtilities.between(0, 1, -0.1));
    }

    @Test
    public void betweenReturnsFalseIfTheBetweenValueIsGreaterThenTheHighValue() throws Exception {
        assertFalse(MathematicalUtilities.between(0, 1, 1.1));
    }

    @Test
    public void betweenReturnsTrueIfTheBetweenValueIsEqualToTheHighValue() throws Exception {
        assertTrue(MathematicalUtilities.between(0, 1, 1));
    }

    @Test
    public void betweenReturnsTrueIfTheBetweenValueIsEqualToTheLowValue() throws Exception {
        assertTrue(MathematicalUtilities.between(0, 1, 0));
    }

    @Test
    public void betweenReturnsTrueIfTheBetweenValueIsBetweenTheHighAndTheLowValue() throws Exception {
        assertTrue(MathematicalUtilities.between(0, 1, 0.5));
    }

    @Test
    public void betweenReturnsFalseIfTheLowValueIsGreaterThenTheHighValue() throws Exception {
        assertFalse(MathematicalUtilities.between(1.1, 1,  1.1));
    }

    @Test
    public void isDivisorOfReturnsTrueIfTheDivisorIsAValidDivisorOfTheDividend() {
        assertTrue(MathematicalUtilities.isDivisorOf(5, 10));
    }

    @Test
    public void isDivisorOfReturnsFalseIfTheDivisorIsNotAValidDivisorOfTheDividend() {
        assertFalse(MathematicalUtilities.isDivisorOf(6, 10));
    }

    @Test
    public void equalsBetweenTwoPointsReturnsTrueIfBothPointsAreEqual() throws Exception {
        assertTrue(MathematicalUtilities.equals(new Triple(1, 2, 3), new Triple(1, 2, 3)));
    }

    @Test
    public void equalsBetweenTwoPointsReturnsFalseIfBothPointsAreNotEqual() throws Exception {
        assertFalse(MathematicalUtilities.equals(new Triple(1, 2, 3), new Triple(5, 8, 9)));
    }

    @Test(expected = IllegalArgumentException.class)
    public void equalsBetweenTwoPointsThrowsIllegalArgumentExceptionIfPointAIsNull() throws Exception {
        MathematicalUtilities.equals(new Triple(1, 2, 3), null);
    }

    @Test(expected = IllegalArgumentException.class)
    public void equalsBetweenTwoPointsThrowsIllegalArgumentExceptionIfPointBIsNull() throws Exception {
        MathematicalUtilities.equals(null, new Triple(1, 2, 3));
    }

	@Test(expected = IllegalArgumentException.class)
	public void determinantRequiresFirstRowOrColumn() {
	   MathematicalUtilities.determinant(null, new Triple(1, 2, 3), new Triple(1, 4, 9));
	}

	@Test(expected = IllegalArgumentException.class)
	public void determinantRequiresSecondRowOrColumn() {
	   MathematicalUtilities.determinant(new Triple(1, 2, 3), null, new Triple(1, 4, 9));
	}

	@Test(expected = IllegalArgumentException.class)
	public void determinantRequiresThirdRowOrColumn() {
	    MathematicalUtilities.determinant(new Triple(1, 2, 3), new Triple(1, 4, 9), null);
	}

	@Test
	public void determinantReturnsCorrectValue() {
		Triple firstRowOrColumn = new Triple(-2, 2, -3);
		Triple secondRowOrColumn = new Triple(-1, 1, 3);
		Triple thirdRowOrColumn = new Triple(2, 0, -1);
		assertRealEquals(18, MathematicalUtilities.determinant(firstRowOrColumn, secondRowOrColumn, thirdRowOrColumn));
	}
}
